package cn.edu.scnu.user.controller;

import cn.edu.scnu.annotation.IgnoreToken;
import cn.edu.scnu.pojo.PersonalUser;
import cn.edu.scnu.pojo.User;
import cn.edu.scnu.pojo.UserInfo;
import cn.edu.scnu.user.service.OrgService;
import cn.edu.scnu.user.service.UserService;
import cn.edu.scnu.utils.CookieUtils;
import cn.edu.scnu.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@RestController
@Api
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private OrgService orgService;
    @Lazy
    @Resource(type = RestTemplate.class)
    private RestTemplate restTemplate;


    @IgnoreToken
    @PostMapping("/users/login")
    @ApiOperation("用户登录")
    @ApiImplicitParam(
            name = "user",
            value = "用户",
            dataType = "cn.edu.scnu.pojo.user",
            required = true
    )
    public SysResult doLogin(@RequestBody User user, HttpServletRequest request, HttpServletResponse response) {

        String ticket = userService.doLogin(user);
        if (StringUtils.isNotEmpty(ticket)) {
            CookieUtils.setCookie(request, response, "EM_TICKET", ticket);
            UserInfo userInfo = null;
            userInfo = userService.getUserByUname(user.getUsername());
            if (userInfo == null)
                userInfo = orgService.getOrgByUname(user.getUsername());
            return SysResult.build(ResultCode.SUCCESS, "登录成功", userInfo);
        }
        return SysResult.build(ResultCode.NOT_FOUND, "用户名或密码错误！", null);
    }

    @DeleteMapping("/users/logout")
    @ApiOperation("退出登录")
    public SysResult doLogout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();
        userService.doLogout(user);
        return SysResult.build(ResultCode.NO_CONTENT, "no content", null);
    }

    @IgnoreToken
    @GetMapping("/users/queryticket")
    @ApiOperation("验证用户是否登录")
    public SysResult checkLoginUser(HttpServletRequest request) {
        String ticket = request.getHeader("token");
        String userJson = userService.queryUserJson(ticket);

        if (StringUtils.isNotEmpty(userJson)) {
            return SysResult.build(ResultCode.SUCCESS, "success", userJson);
        } else {
            return SysResult.build(ResultCode.UNAUTHORIZED, "未登录", null);
        }
    }

    @IgnoreToken
    @GetMapping("/users/check/{username}")
    @ApiOperation("检查用户名是否已存在")
    @ApiImplicitParam(
            name = "username",
            value = "用户名",
            dataType = "String",
            required = true,
            paramType = "path"
    )
    public SysResult checkUsername(@PathVariable String username) {
        if (userService.checkUsername(username) == null) {
            return SysResult.ok();
        }
        return SysResult.build(ResultCode.FAIL, "username exist!", null);
    }

    @IgnoreToken
    @PostMapping("/users")
    @ApiOperation("用户注册")
    @ApiImplicitParam(
            name = "user",
            value = "用户",
            dataType = "cn.edu.scnu.pojo.User",
            required = true,
            type = "body"
    )
    public SysResult registerUser(@RequestBody User user) {
        if (userService.checkUsername(user.getUsername()) != null) {
            return SysResult.build(ResultCode.FAIL, "create fail", null);
        }
        userService.registerUser(user);
        return SysResult.build(ResultCode.CREATED, "create success!", null);
    }

    @PutMapping("/users")
    @ApiOperation("修改用户信息")
    @ApiImplicitParam(
            name = "user",
            value = "用户信息",
            dataType = "cn.edu.scnu.pojo.PersonalUser",
            required = true,
            type = "body"
    )
    public SysResult saveUser(@RequestBody PersonalUser user) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user1 = (User) authentication.getPrincipal();
        if (!user.getUsername().equals(user1.getUsername())) {
            return SysResult.build(ResultCode.FORBIDDEN, "权限错误", null);
        }
        userService.saveUser(user);
        return SysResult.build(ResultCode.CREATED, "update success", user);
    }

    @IgnoreToken
    @GetMapping("/users/{username}")
    @ApiOperation("查看用户信息")
    @ApiImplicitParam(
            name = "username",
            value = "用户名",
            dataType = "String",
            required = true,
            type = "path"
    )
    public SysResult getUserByUname(@PathVariable String username) {
        PersonalUserVO user = userService.getUserByUname(username);
        if (user != null) {
            return SysResult.build(ResultCode.SUCCESS, "success", user);
        }
        return SysResult.build(ResultCode.NOT_FOUND, "not found", null);

    }

//    @IgnoreToken
//    @GetMapping("/users/{username}/matchs")
//    @ApiOperation("获取用户参加的比赛")
//    public SysResult getAllMatchByUname(@PathVariable String username) {
//        //TODO
//        return SysResult.build(ResultCode.NOT_FOUND, "not found", null);
//    }

    @PutMapping("/users/nickname/{nickname}")
    @ApiOperation("修改昵称")
    @ApiImplicitParam(
            name = "nickname",
            value = "昵称",
            dataType = "String",
            required = true,
            type = "path"
    )
    public SysResult updateNick(@PathVariable String nickname) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();
        userService.updateNick(user.getUsername(), nickname);
        return SysResult.build(ResultCode.CREATED, "update success", null);
    }

    @PostMapping("/users/img")
    @ApiOperation("修改头像")
    @ApiImplicitParam(
            name = "file",
            value = "头像",
            required = true
    )
    public SysResult updateImg(MultipartFile file) throws IOException {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();

        ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) {
            @Override
            public String getFilename() {
                return file.getOriginalFilename();
            }

            @Override
            public long contentLength() {
                return file.getSize();
            }
        };
        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("pic", fileAsResource);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity(multiValueMap, headers);

        PicUploadResult result = restTemplate.postForObject("http://picService/pic/manage/upload", requestEntity, PicUploadResult.class);
        if (result.getError() == 1) {
            return SysResult.build(ResultCode.FAIL, "update fail", null);
        }
        String url = result.getUrl();
        System.out.println(url);
        userService.updateImg(user.getUsername(), url);
        return SysResult.build(ResultCode.CREATED, "update success", null);
    }

    @IgnoreToken
    @GetMapping("/users/{username}/info")
    @ApiOperation("获取用户头像昵称")
    @ApiImplicitParam(
            name = "username",
            value = "用户名",
            dataType = "String",
            required = true
    )
    public SysResult getInfoByUsername(@PathVariable String username) {
        Map<String, String> map = userService.getInfoByUsername(username);
        if (map != null) {
            return SysResult.build(ResultCode.SUCCESS, "success", map);
        }
        return SysResult.build(ResultCode.NOT_FOUND, "not found", null);
    }

    @IgnoreToken
    @GetMapping("/users/search/{nickname}")
    @ApiOperation("搜索用户")
    @ApiImplicitParam(name = "nickname", value = "昵称", dataType = "String", required = true, type = "path")
    public SysResult searchUsersByNickname(@PathVariable String nickname) {
        List<Card> cards = userService.searchUsersByNickname(nickname);
        return SysResult.build(ResultCode.SUCCESS, "success", cards);
    }

}
